﻿#region Copyrigth and License
/*==============================================================================
 *  Copyright (c) cndotnet.org Corporation.  All rights reserved.
 * ===============================================================================
 * This code and information is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the implied warranties
 * of merchantability and fitness for a particular purpose.
 * ===============================================================================
 * Licensed under the GNU General Public License (GPL) v2
 * http://www.cndotnet.org/ezsocio
 * ==============================================================================*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Reflection;
using System.Web;
using System.Net;
using System.IO;
using System.Web.Configuration;

namespace DusonFramework.ContactService.LiveID
{
    #region 该类用于获取msn联系人
    /// <summary>
    /// 该类用于获取msn联系人
    /// </summary>
    public class LiveIDService {
        #region Fields
        static readonly string AuthCookie = WebConfigurationManager.AppSettings["delAuthCookie"];
        #endregion

        #region Constructors

        #endregion

        #region Properties

        #endregion

        #region Events

        #endregion

        #region Methods
        /// <summary>
        /// 获取msn联系人分组信息
        /// </summary>
        /// <returns></returns>
        public static DusonFramework.ContactService.LiveID.LiveContractCollection GetLiveContracts() {
            WindowsLiveLogin wll = new WindowsLiveLogin(true);
            HttpCookie authCookie = HttpContext.Current.Request.Cookies[AuthCookie];
            if (authCookie == null) {
                //当前还没有征得用户的同意，所以接下来要进行DelegateAuth
            }
            string lid = null;
            long llid = 0;
            string delegatedToken = null;
            string t = authCookie.Value;
            var Token = wll.ProcessConsentToken(t);
            if (Token != null) {
                lid = Token.LocationID;
                llid = Int64.Parse(lid, System.Globalization.NumberStyles.HexNumber);
                delegatedToken = Token.DelegationToken;
            }
            string uri = "https://livecontacts.services.live.com/users/@C@" + llid.ToString() + "/rest/LiveContacts";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
            request.UserAgent = "Windows Live Data Interactive SDK";
            request.Method = "GET";
            request.Headers.Add("Authorization", "DelegatedToken dt=\"" + delegatedToken + "\"");
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
                XmlDocument contacts = new XmlDocument();
                using (var sr = new StreamReader(response.GetResponseStream())) {
                    contacts.LoadXml(sr.ReadToEnd());
                    response.Close();
                    var root = contacts.DocumentElement;
                    LiveContractGroupCollection lcc = new LiveContractGroupCollection();
                    lcc.Owner = GetOwner(root);
                    List<LiveContract> contractList = GetContracts(root);
                    List<LiveContractGroup> contractGroup = GetGroups(root, contractList);
                    lcc.AddRange(contractGroup);
                    LiveContractCollection col = new LiveContractCollection();
                    foreach (var group in lcc) {
                        col.AddRange(group.Contracts);
                    }
                    return col;
                }
            }
        }

        static LiveOwner GetOwner(XmlNode root) {
            Type t = typeof(LiveOwner);
            PropertyInfo[] pis = t.GetProperties();
            XmlNodeMapping classAttr = Attribute.GetCustomAttribute(t, typeof(XmlNodeMapping)) as XmlNodeMapping;
            string path = classAttr.XmlNodeName;
            var node = root.SelectSingleNode(path);
            if (node == null) {
                return null;
            }
            LiveOwner lo = new LiveOwner();
            foreach (PropertyInfo pi in pis) {
                XmlNodeMapping attr = Attribute.GetCustomAttribute(pi, typeof(XmlNodeMapping)) as XmlNodeMapping;
                string p = string.Format("{0}/{1}", path, attr.XmlNodeName);
                var n = root.SelectSingleNode(p);
                if (n != null) {
                    pi.SetValue(lo, Convert.ChangeType(n.InnerText, pi.PropertyType), null);
                }
            }
            return lo;
        }

        static List<LiveContractGroup> GetGroups(XmlNode root, List<LiveContract> contracts) {
            List<LiveContractGroup> list = new List<LiveContractGroup>();
            Type t = typeof(LiveContractGroup);
            PropertyInfo[] pis = t.GetProperties();
            XmlNodeMapping classAttr = Attribute.GetCustomAttribute(t, typeof(XmlNodeMapping)) as XmlNodeMapping;
            string path = classAttr.XmlNodeName;
            var node = root.SelectNodes(path);
            if (node == null || node.Count == 0) {
                LiveContractGroup lg = new LiveContractGroup();
                lg.ID = "-1";
                lg.Name = "未分组";
                lg.Contracts.AddRange(contracts);
                foreach (LiveContract lc in contracts) {
                    lg.Contracts.Add(lc);
                    lc.GroupID = "-1";
                }
                list.Add(lg);
                return list;
            }
            foreach (XmlNode n in node) {
                LiveContractGroup lg = new LiveContractGroup();
                SetValue(t, lg, n);
                foreach (string id in lg.ContractIDs) {
                    var lcs = from contract in contracts where contract.ID == id select contract;

                    if (lcs != null) {
                        foreach (LiveContract c in lcs) {
                            c.GroupID = lg.ID;
                            lg.Contracts.Add(c);
                        }
                    }
                }
                list.Add(lg);
            }
            return list;
        }

        static List<LiveContract> GetContracts(XmlNode root) {
            List<LiveContract> list = new List<LiveContract>();
            Type t = typeof(LiveContract);
            PropertyInfo[] pis = t.GetProperties();
            XmlNodeMapping classAttr = Attribute.GetCustomAttribute(t, typeof(XmlNodeMapping)) as XmlNodeMapping;
            string path = classAttr.XmlNodeName;
            var node = root.SelectNodes(path);
            if (node == null || node.Count == 0) {
                return list;
            }
            foreach (XmlNode n in node) {
                LiveContract lc = new LiveContract();
                SetValue(t, lc, n);
                list.Add(lc);
            }
            return list;
        }
        static void SetValue(Type t, object o, XmlNode node) {
            PropertyInfo[] pis = t.GetProperties();
            foreach (PropertyInfo pi in pis) {
                XmlNodeMapping attr = Attribute.GetCustomAttribute(pi, typeof(XmlNodeMapping)) as XmlNodeMapping;
                if (attr != null) {
                    if (attr.IsCollection) {
                        var nodes = node.SelectNodes(attr.XmlNodeName);
                        var list = Activator.CreateInstance(pi.PropertyType) as System.Collections.IList;
                        foreach (XmlNode n in nodes) {
                            if (n != null) {
                                list.Add(n.InnerText);
                            }
                        }
                        pi.SetValue(o, Convert.ChangeType(list, pi.PropertyType), null);
                    }
                    else {
                        var n = node.SelectSingleNode(attr.XmlNodeName);
                        if (n != null) {
                            pi.SetValue(o, Convert.ChangeType(n.InnerText, pi.PropertyType), null);
                        }
                    }
                }
                else {
                    XmlNodeMapping classAttr = Attribute.GetCustomAttribute(pi.PropertyType, typeof(XmlNodeMapping)) as XmlNodeMapping;
                    if (classAttr == null) {
                        continue;
                    }
                    string path = classAttr.XmlNodeName;
                    XmlNode n = node.SelectSingleNode(path);
                    if (n != null) {
                        object oo = Activator.CreateInstance(pi.PropertyType);
                        SetValue(pi.PropertyType, oo, n);
                        pi.SetValue(o, oo, null);
                    }
                }
            }
        }
        #endregion
    }
    #endregion
}
